
//epoll io
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>


int my_listen(int port)
{
	int fd = -1;
	int ret = -1;

	fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0)  {
		printf("fd error\n");
		return -1;
	}


	struct sockaddr_in server_addr = {0};
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(port);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);	

	ret = bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if(ret < 0) {
		printf("bind error\n");
		return -1;
	}

	ret = listen(fd, 5);
	if(ret < 0)  {
		printf("listen error\n");
		return -2;
	}

	return fd;
}



char buff[1024] = {0};


int main(int argc, char **argv)
{
	if(argc != 2) {
		printf("error\n");
		return -1;
	}

	int port = atoi(argv[1]);
	int i = 0;
	int rsize = 0;

	int epfd = epoll_create(1);

	struct epoll_event event = {0};
	struct epoll_event client_event[100] = {0};

	printf("port %d\n", port);

	int sockfd = my_listen(port);
	fcntl(sockfd, F_SETFL, O_NONBLOCK);

		
	event.data.fd = sockfd;
	event.events = EPOLLIN;
	epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);



	while(1) {

		
		int nread = epoll_wait(epfd, client_event, 100, 0);
		if (nread < 0) {
			continue;
		}

		for(i=0; i<nread; i++)  {
			memset(&event, 0, sizeof(event));
			if(client_event[i].data.fd == sockfd) {
				//epoll_ctl(epfd, EPOLL_DEL, client_event[i].data.fd, NULL);

				struct sockaddr client_addr  = {0};
				socklen_t len = 0;
	
				int client_fd = accept(sockfd, &client_addr, &len);

				
				event.data.fd = client_fd;
				event.events = EPOLLIN;
				epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &event);
				
			} else {
				epoll_ctl(epfd, EPOLL_CTL_DEL, client_event[i].data.fd, NULL);
				if(client_event[i].events == EPOLLIN) {
					

					rsize = recv(client_event[i].data.fd, buff,  sizeof(buff), 0);
					if(rsize <= 0)
						continue;
				
					printf("recv %s\n", buff);
					event.data.fd = client_event[i].data.fd;
					event.events = EPOLLOUT;
					epoll_ctl(epfd, EPOLL_CTL_ADD, client_event[i].data.fd, &event);
				} else if(client_event[i].events == EPOLLOUT) {
					send(client_event[i].data.fd,  buff, sizeof(buff), 0);
					printf("send %s\n", buff);
					memset(&buff, 0, sizeof(buff));
					event.data.fd = client_event[i].data.fd;
					event.events = EPOLLIN;
					epoll_ctl(epfd, EPOLL_CTL_ADD, client_event[i].data.fd, &event);
				}


			}

		}


	}


	return 0;
}




















